package com.eastfair.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.pay.dao.ContractMapper;
import com.eastfair.pay.dto.ContractDTO;
import com.eastfair.pay.enums.PayStateEnum;
import com.eastfair.pay.vo.ContractFinanceVO;
import com.eastfair.pay.dto.PaymentPlanDTO;
import com.eastfair.pay.entity.CollectRecord;
import com.eastfair.pay.entity.Contract;
import com.eastfair.pay.entity.PaymentPlan;
import com.eastfair.pay.exceptioncode.PayExceptionCode;
import com.eastfair.pay.service.CollectRecordService;
import com.eastfair.pay.service.ContractService;
import com.eastfair.boot.service.SuperServiceImpl;

import com.eastfair.pay.service.PaymentPlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 业务实现类
 * 合同
 * </p>
 *
 * @author clm
 * @date 2022-06-08
 */
@Slf4j
@Service
public class ContractServiceImpl extends SuperServiceImpl<ContractMapper, Contract> implements ContractService {

    @Resource
    private PaymentPlanService paymentPlanService;

    @Resource
    private CollectRecordService collectRecordService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<Contract> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }


    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(Contract model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        return R.successDef();
    }

    /**
     * @param contractDTO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(ContractDTO contractDTO) {

        //合同的认领记录
        List<CollectRecord> collectRecordList = collectRecordService.queryCollectRecordList(contractDTO.getContractId());
        if(!CollectionUtil.isEmpty(collectRecordList)){
            throw BizException.wrap(PayExceptionCode.CONTRACT_HAS_COLLECTED);
        }

        Contract sourceContract = getById(contractDTO.getContractId());
        Contract contract = BeanUtil.copyProperties(contractDTO, Contract.class);
        if (sourceContract != null){
            contract.setId(sourceContract.getId());
        }
        saveOrUpdate(contract);

        List<PaymentPlanDTO> paymentPlanDTOList = contractDTO.getPaymentPlanDTOList();
        List<PaymentPlan> paymentPlans = ConvertUtil.convertList(paymentPlanDTOList, PaymentPlan.class);
        BigDecimal planAmount = new BigDecimal(0);
        for (PaymentPlan item : paymentPlans){
            planAmount = planAmount.add(item.getPlanPayAmount());
            item.setBusinessId(contract.getContractId());
            item.setProjectId(ContextUtil.getProjectId());
            item.setSubsystemId(ContextUtil.getSubSystemId());
            item.setTenantId(ContextUtil.getTenantId());
        }
        //判断合同金额是否等于付款计划总和
        if (contract.getContractAmount().compareTo(planAmount) != 0){
            throw BizException.wrap(PayExceptionCode.CONTRACT_PLAN_AMOUNT_NOT_EQ);
        }
        paymentPlanService.saveOrUpdateBatch(paymentPlans);
    }

    /**
     * true 有人领记录    false  则无
     * @param contractId
     * @return
     */
    @Override
    public Boolean isCollected(Long contractId) {
        List<CollectRecord> collectRecordList = collectRecordService.queryCollectRecordList(contractId);
        return !CollectionUtil.isEmpty(collectRecordList);
    }

    /**
     * 删除合同
     * @param contractId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(Long contractId) {
        if (isCollected(contractId)){
           return;
        }
        paymentPlanService.deleteByContractId(contractId);
        Contract contract = getByBusinessId(contractId);
        removeByIdsOfLogic(new ArrayList<Contract>(){
            {
                add(contract);
            }
        });
    }

    /**
     * @param businessId
     * @return
     */
    @Override
    public Contract getByBusinessId(Long businessId) {
        LambdaQueryWrapper<Contract> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(businessId != null, Contract::getContractId, businessId);
        lambdaQueryWrapper.last("limit 1");
        return baseMapper.selectOne(lambdaQueryWrapper);
    }

    /**
     * @Author clm
     * @Description //获取合同财务数据
     * @Date 18:48 2022/7/8
     * @Param [contractId]
     * @return com.eastfair.pay.vo.ContractFinanceVO
     **/
    @Override
    public ContractFinanceVO queryFinance(Long contractId) {
        ContractFinanceVO contractFinanceVO = new ContractFinanceVO();
        Contract contract = getByBusinessId(contractId);
        List<PaymentPlan> paymentPlans = paymentPlanService.queryByBusinessId(contractId);
        if (!CollectionUtil.isEmpty(paymentPlans)){
            BigDecimal payedAmount = new BigDecimal(0);
            int finishTotal = 0;
            int overdueTotal= 0;
            for (PaymentPlan paymentPlan : paymentPlans){
                payedAmount = payedAmount.add(paymentPlan.getPayedAmount());
                if (PayStateEnum.PAYED.getCode().equals(paymentPlan.getPayState())){
                    finishTotal ++;
                }
                if (paymentPlan.getPlanPayTime().compareTo(LocalDateTime.now()) == 1){
                    overdueTotal ++;
                }
            }
            contractFinanceVO.setFinishTotal(finishTotal + "期");
            contractFinanceVO.setOverdueTotal(overdueTotal + "期");
            contractFinanceVO.setPayPlanTotal(paymentPlans.size() + "期");
            contractFinanceVO.setLastPayTime(paymentPlans.get(paymentPlans.size() - 1).getPlanPayTime());
            contractFinanceVO.setPayedAmount(payedAmount);
            contractFinanceVO.setUnPayedAmount(contract.getContractAmount().subtract(payedAmount));
            contractFinanceVO.setInvoiceAmount(contract.getInvoicedAmount());
            contractFinanceVO.setUnInvoiceAmount(contract.getSpaceAmount().subtract(contract.getInvoicedAmount()));
        }
        return contractFinanceVO;
    }

}
